#ifndef IMAGEUTILS_H_
#define IMAGEUTILS_H_

#include <string>

#include <cxcore.h>
#include <cv.h>


class Pixel;
class Blob;

/** 
 * This class is a collection of several utility function for IplImage handling.
 * Most of these functions are not included in OpenCV (or I haven't found them yet)
 * but are still needed quite often (in my projects, at least). 
 * 
 * The most frequently used (and needed) functions are those to access pixel values, 
 * as OpenCV does not provide any method for that but rather requires the user to
 * do some pointer arithmetics on the raw data arrays.
 * All access on pixel values is checked for boundary violations. This is done by
 * assertion, so trying to access any pixel out-of-bounds will cause the program 
 * to abort.
 * Furthermore, all access can be done using the Pixel class.
 * 
 * @author Moritz Vieth
 **/
class ImageUtils
{
private:
	ImageUtils();
	virtual ~ImageUtils();
	
	
public:

	static const int ORDER_BGR = 0x01; 
	static const int ORDER_RGB = 0x02; 
	
	
	
	
/*************** METHODS ***************/

public:
	
	
	/* get/set Pixels or pixel values */
	static int getPixelValue(IplImage *image, int x, int y);
    static int getPixelValue(IplImage *image, CvPoint point);
    static int getPixelValue(IplImage *image, int x, int y, int channel);
    static int getPixelValue(IplImage *image, CvPoint point, int channel);
    static Pixel getPixel(IplImage *image, int x, int y, int numChannels = 3);
    static Pixel getPixel(IplImage *image, CvPoint point, int numChannels = 3);
    
    
    static void setPixelValue(IplImage* image, int x, int y, int channel, int value);
    static void setPixelValue(IplImage* image, CvPoint point, int channel, int value);
    static void setPixelValue(IplImage* image, int x, int y, int num_channels, int* value, int order = ORDER_BGR);
    static void setPixelValue(IplImage* image, CvPoint point, int num_channels, int* value, int order = ORDER_BGR);
    static void setPixel(IplImage* image, Pixel pixel);
	
	
    /* Create a CvRect from two points. */
	static CvRect getCvRect(CvPoint a, CvPoint b);

	/* Copy a region from one IplImage to another */
	static void copyRegion(IplImage* src, IplImage* dst, CvPoint start, CvPoint end);
    
    
	static void drawArrow(IplImage* image, CvPoint start, CvPoint end, CvScalar color, int thickness = 1, int stretchFactor = 1);
    static void drawRect(IplImage* image, CvRect rect, CvScalar color, bool filled = false);
    static void drawBox2D(IplImage* image, CvBox2D box, CvScalar color, bool filled);
    static void drawBox2D(IplImage* image, CvBox2D box, CvScalar color);
    static void drawBox2DFilled(IplImage* image, CvBox2D box, CvScalar color);
    static void drawPolyLine(IplImage* image, CvPoint* points, int nPoints, CvScalar color, int thickness = 1);
    static void drawAsymmetricBox(IplImage* image, CvPoint a, CvPoint b, CvPoint c, CvPoint d, CvScalar color);
    
    //TODO mit variablem Gedöns machen
    static void writeText(IplImage* image, std::string text, CvPoint coordinates, CvScalar color, double size = 1.0, int thickness = 1);
    
    static CvScalar getColorDifference(CvScalar colorA, CvScalar colorB);
    
    
    static void createMask(IplImage* image, IplImage* mask); 
    static void copyByMask(IplImage* src, IplImage* dst, IplImage* mask);
    
    static IplImage* getMaskFromCvBox2D(CvBox2D box, int width, int height);
    
    
    static bool overlaps(CvRect a, CvRect b, int distance = 0);
    static double getOverlap(CvRect a, CvRect b);
    
    
    /* vom cbr-projekt */
    static float** convertImageToResizedGray( IplImage* img, int newWidth, int newHeight );
    static float** convertIplImageToFloat( IplImage *img );
    static IplImage* getSubImage(IplImage* src, CvPoint start, CvPoint end);
    static IplImage* getSubImageAsGray(IplImage* src, CvPoint start, CvPoint end);

private:
	static float fitRange(float value, float low, float high);
    
/*************** MEMBERS ***************/
    
protected:

	const static int MAX_MARKER_COLORS = 63;
	
	static CvScalar markerColors[];
	
	
};

#endif /*UTILS_H_*/
 
